package com.wili.c;
import java.util.List;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.c.Ca;
@SuppressWarnings("all")
public class Str9 {
	public static String nl2;//reference test.

	public static final String NL = "".isEmpty() ? System.lineSeparator() : "\n";
	public static String findPat(String regexp, int group, String s0, int start) {
		//eg. Str9.findPat("(^|\\+)([A-Z])([^\\w]|$)", 2, "C+Bc+Ad", 0);//返回C
		MatchResult ret = findPatGroups(regexp, s0, start);
		return ret == null ? null : ret.group(group);
	}

	public static MatchResult findPatGroups(String regexp, String s0, int fromInd) {
		Pattern pat = Pattern.compile(regexp, Pattern.DOTALL);
		Matcher mat = pat.matcher(s0);
		mat.region(fromInd, s0.length());
		if (mat.find()) {
			//s0.substring(mat.start());
			return mat.toMatchResult();
		}
		return null;
	}

	public static boolean isEscapedAt(int ind, String str, char esc) {
		boolean is = false;
		while (--ind >= 0) {
			char ch = str.charAt(ind);
			if (ch == esc) {
				is = !is;
			} else {
				return is;
			}
		}
		return is;
	}

	/**
	 * 用字串中的相同位置内容，替换stringBuilder中的内容。
	 */
	public static void replaceStringBuilderContent(StringBuilder sb, List<int[]> indss, String s0) {
		if (indss == null)
			return;
		for (int i = 0; i < indss.size(); i++) {
			int[] inds = indss.get(i);
			String st = s0.substring(inds[0], inds[1]);
			sb.replace(inds[0], inds[1], st);
		}
	}

	/**
	 * 用等长的占位符，取代字串中给定的下标范围。
	 */
	public static String replaceAllRangeList_withChars(List<int[]> indss, char withChar, String s0) {
		if (Boolean.FALSE)
			replaceStringBuilderContent(null, null, s0);
		if (indss == null)
			return s0;
		String withChar_ = String.valueOf(withChar);
		StringBuilder sb = new StringBuilder(s0.length());
		int from = 0;
		for (int i = 0; i < indss.size(); i++) {
			int[] inds = indss.get(i);
			String str = s0.substring(from, inds[0]);
			sb.append(str);
			String content = s0.substring(inds[0], inds[1]);
			if ("".isEmpty()) {
				content = content.replaceAll("[^\r\n]", withChar_);
				sb.append(content);
			} else {
				sb.append(Str9.repeat(withChar, inds[1] - inds[0]));
			}
			from = inds[1];
		}
		sb.append(s0.substring(from));
		return sb.toString();
	}
	static final String NULL = "null";
	public static String repeat(char c, int times) {
		if (c == ' ') {
			if (times <= bigSpace.length())
				return bigSpace.substring(0, times);
			StringBuilder sb = new StringBuilder(times);
			int n = times / bigSpace.length();
			for (int i = 0; i < n; i++) {
				sb.append(bigSpace);
			}
			sb.append(bigSpace.substring(0, times % bigSpace.length()));
			Ca.asert(sb.length() == times, times);
			return sb.toString();
		}
		return repeat(c, times, "", -1, "");
	}

	static String repeat(char c, int times, String deli, int step, String deli2) {
		if (times <= 0)
			return "";
		StringBuilder sb = new StringBuilder(times);
		for (int i = 0; i < times; i++) {
			if (i > 0) {
				if (step != -1 && i % step == 0) {
					sb.append(deli2);
				} else {
					sb.append(deli);
				}
			}
			sb.append(c);
		}
		return sb.toString();
	}

	/**
	 * find chs[i] in s0. skip char which escaped by '\'.<br>
	 * @return [index-in-s0, index-in-chars].
	 */
	public static int[] indexOfAnyChar(String s0, int from, char... chars) {
		int len = s0.length();
		for (int i = from; i < len; i++) {
			char ch = s0.charAt(i);
			for (int j = 0; j < chars.length; j++) {
				if (ch == chars[j])
					return new int[] { i, j };
			}
		}
		return null;
	}

	/**
	 * @return  indexOf($R)+1
	 */
	public static int readBracket(final char L, final char R, String s0, int start, int end) {
		return readBracket00(L, R, s0, start, end, false);
	}

	static int readBracket00(final char L, final char R, String s0, int start, int end, boolean skipJavaNotation) {
		if (s0.charAt(start) != L)
			return -1;
		int left = 0;
		for (int i = start; i < end; i++) {
			char ch = s0.charAt(i);
			if (ch == L) {
				left++;
				continue;
			} else if (ch == R) {
				if (--left == 0) {
					return i + 1;
				}
				continue;
			} else if (ch == '"' || ch == '\'') {
				String qt = readQuote(s0, i);
				i += qt.length() - 1;
			} else if (skipJavaNotation) {
				if (s0.startsWith("//", i)) {
					i = s0.indexOf('\n', i + 2);
				} else if (s0.startsWith("/*", i)) {
					i = s0.indexOf("*/", i + 2) + 1;
				}
			}
		}
		return -1;
	}

	/**
	 * 读入一个括号范围(考虑引号、不考虑转义字符)。
	 */
	public static String readBracket(String s0, int start, boolean ignoresAngleBracket) {
		if (start >= s0.length())
			return null;
		if (!"([{<".contains(String.valueOf(s0.charAt(start))))
			return null;
		int left = 1;
		String st;
		for (int i = start + 1; i < s0.length(); i++) {
			char ch = s0.charAt(i);
			//System.out.print(ch);
			switch (ch) {
			case '<':
				if (ignoresAngleBracket)
					continue;//可能是小于号
				Ca.pause();
			case '(':
			case '[':
			case '{'://读入左括号
				left++;
				continue;
			case '>'://读入右括号
				if (ignoresAngleBracket)
					continue;
			case ')':
			case ']':
			case '}'://读入右括号
				left--;
				break;
			case '\''://计入单引号
				st = readQuote(s0, i);//shouldn't return null.
				i += st.length() - 1;
				continue;
			case '"'://读入双引号
				st = readQuote(s0, i);
				i += st.length() - 1;
				continue;
			}
			if (left == 0)
				return s0.substring(start, i + 1);
		}
		return null;
	}

	public static String readQuote(String s0, int start) {
		//		s0.substring(start);
		//System.out.println(s0.substring(start));
		char quote = s0.charAt(start);
		String st = s0.substring(start);
		if (quote != '"' && quote != '\'')
			return null;
		int ind = s0.indexOf(quote, start + 1);
		while (ind != -1) {
			if (!isEscapedAt(ind, s0)) {
				return s0.substring(start, ind + 1);
			}
			ind = s0.indexOf(quote, ind + 1);
		}
		Ca.pause();
		throw new RuntimeException();
	}

	public static boolean isEscapedAt(int ind, String s0) {
		return isEscapedAt(ind, s0, '\\');
	}
	static final String bigSpace = "                                                                   "
			+ "                                                                                    "
			+ "                                                                                    "
			+ "                                                                                    "
			+ "                                                                                    ";

	static final String bigDots = "----------------------------------------------";

	static final String tabs = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
	/**
	 * .. Pattern is 8 times faster than regexpString.
	 */
	public static String replaceAll(Pattern pat, String replacement, String s0, int start) {
		if (start == 0)
			return pat.matcher(s0).replaceAll(replacement);
		return pat.matcher(s0).region(start, s0.length()).replaceAll(replacement);
	}
	/**
	 * 
	 * @param fromInd  子串在母串中的下标
	 * @param subSt  子串
	 * @param nestInds 母串中的括号的起止下标
	 * @param splitChars
	 * @return 子串集(带相对起止下标)
	 */
	private static final Pattern _removeGenericType = Pattern.compile("<.*>");
	/**
	 * 	移除泛型信息。eg. Class<?>[] ~> Class[],  Map<Object,Set<V>> ~> Map
	 */
	public static String removeGenericType(String expSt) {
		return _removeGenericType.matcher(expSt).replaceAll("");
	}

	/**
	 * @param paramsSt  eg. "char ch, int from, String s0"
	 * @return
	 */
	public static String[][] getParamTypeNames_and_varNames(String paramsSt) {
		if (paramsSt.isEmpty())
			return new String[2][0];
		String st = Str9.removeGenericType(paramsSt);
		String[] paramArray = st.split(",");
		String[] types = new String[paramArray.length], names = new String[paramArray.length];
		for (int i = 0; i < paramArray.length; i++) {
			String[] typeAndName = paramArray[i].trim().split("\\s+");
			types[i] = typeAndName[0].trim();
			names[i] = typeAndName[1].trim();
		}
		return new String[][] { types, names };
	}

	public static int indexOfChar_skipBracket(char ch, String fromSt, int from, char... lrs) {
		int len = fromSt.length();
		//System.out.println();
		//System.out.println(fromSt.substring(from,from+50));
		f1: for (int i = from; i < len; i++) {
			char curCh = fromSt.charAt(i);
			//System.out.print(curCh);
			if (curCh == ch)
				return i;
			for (int j = 0; j < lrs.length; j += 2) {
				if (curCh == lrs[j]) {
					i = readBracket(lrs[j], lrs[j + 1], fromSt, i, len);
					--i;
					continue f1;
				}
			}
		}
		return -1;
	}

	public static String trimL(String st) {
		for (int i = 0; i < st.length(); i++) {
			char ch = st.charAt(i);
			if (Character.isWhitespace(ch))
				continue;
			if (Boolean.FALSE)
				if (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t')
					continue;
			return st.substring(i);
		}
		return "";
	}

	public static String trimR(String st) {
		if ("".isEmpty()) {
			for (int i = st.length() - 1; i >= 0; i--) {
				char ch = st.charAt(i);
				if (Character.isWhitespace(ch))
					continue;
				return st.substring(0, i + 1);
			}
			return "";
		}
		String st1 = st;
		st = st.trim();
		if (st1.length() == st.length())
			return st1;
		int ind = st1.lastIndexOf(st);
		ind = ind + st.length();
		if (st1.length() == ind)
			return st1;
		return st1.substring(0, ind);
	}
}